package com.pet.platform.service.impl;

import com.pet.platform.common.PageResult;
import com.pet.platform.dto.UserDTO;
import com.pet.platform.dto.UserQueryDTO;
import com.pet.platform.entity.User;
import com.pet.platform.exception.BusinessException;
import com.pet.platform.mapper.UserMapper;
import com.pet.platform.security.dto.AuthResponse;
import com.pet.platform.security.dto.LoginRequest;
import com.pet.platform.security.dto.RegisterRequest;
import com.pet.platform.service.UserService;
import com.pet.platform.util.FileUtil;
import com.pet.platform.util.JwtUtil;
import com.pet.platform.util.SecurityUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class UserServiceImpl implements UserService {

    @Resource
    private UserMapper userMapper;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private JwtUtil jwtUtil;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private FileUtil fileUtil;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userMapper.findByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException("用户不存在");
        }
        return org.springframework.security.core.userdetails.User
                .withUsername(username)
                .password(user.getPassword())
                .authorities(Collections.singletonList(new SimpleGrantedAuthority("ROLE_" + user.getRole())))
                .accountExpired(false)
                .accountLocked(false)
                .credentialsExpired(false)
                .disabled(user.getStatus() == 0)
                .build();
    }

    @Override
    public User findById(Long id) {
        return userMapper.findById(id);
    }

    @Override
    public User findByUsername(String username) {
        return userMapper.findByUsername(username);
    }

    @Override
    public PageResult<UserDTO> findPage(UserQueryDTO queryDTO) {
        Map<String, Object> params = new HashMap<>();
        params.put("username", queryDTO.getUsername());
        params.put("email", queryDTO.getEmail());
        params.put("phone", queryDTO.getPhone());
        params.put("status", queryDTO.getStatus());
        params.put("role", queryDTO.getRole());
        params.put("offset", (queryDTO.getPageNum() - 1) * queryDTO.getPageSize());
        params.put("pageSize", queryDTO.getPageSize());
        params.put("orderBy", queryDTO.getOrderBy());
        params.put("isAsc", queryDTO.getIsAsc());

        List<User> users = userMapper.findList(params);
        Long total = userMapper.count(params);

        List<UserDTO> userDTOs = users.stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());

        return new PageResult<>(userDTOs, total, queryDTO.getPageNum(), queryDTO.getPageSize());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void create(UserDTO userDTO) {
        User user = new User();
        BeanUtils.copyProperties(userDTO, user);
        
        // 设置默认值
        if (user.getRole() == null) {
            user.setRole("USER");
        }
        if (user.getStatus() == null) {
            user.setStatus(1);
        }
        
        // 加密密码
        user.setPassword(passwordEncoder.encode(userDTO.getPassword()));
        
        // 设置创建时间和更新时间
        LocalDateTime now = LocalDateTime.now();
        user.setCreatedTime(now);
        user.setUpdatedTime(now);
        
        userMapper.insert(user);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(Long id, UserDTO userDTO) {
        User existingUser = userMapper.findById(id);
        if (existingUser == null) {
            throw new BusinessException("用户不存在");
        }

        // 如果修改了用户名，检查新用户名是否已存在
        if (!existingUser.getUsername().equals(userDTO.getUsername())
                && userMapper.findByUsername(userDTO.getUsername()) != null) {
            throw new BusinessException("用户名已存在");
        }

        User user = new User();
        BeanUtils.copyProperties(userDTO, user);
        user.setId(id);
        if (userDTO.getPassword() != null && !userDTO.getPassword().isEmpty()) {
            user.setPassword(passwordEncoder.encode(userDTO.getPassword()));
        }
        userMapper.update(user);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(Long id) {
        User existingUser = userMapper.findById(id);
        if (existingUser == null) {
            throw new BusinessException("用户不存在");
        }
        userMapper.delete(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateStatus(Long id, Integer status) {
        User existingUser = userMapper.findById(id);
        if (existingUser == null) {
            throw new BusinessException("用户不存在");
        }

        User user = new User();
        user.setId(id);
        user.setStatus(status);
        userMapper.update(user);
    }

    @Override
    public Long getCurrentUserId() {
        return SecurityUtils.getCurrentUserId();
    }

    @Override
    public AuthResponse login(LoginRequest loginRequest) {
        try {
            Authentication authentication = authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword())
            );
            SecurityContextHolder.getContext().setAuthentication(authentication);

            User user = findByUsername(loginRequest.getUsername());
            String token = jwtUtil.generateToken(user.getUsername());
            
            // 设置当前登录用户
            SecurityUtils.setLoginUser(user);

            AuthResponse response = new AuthResponse();
            response.setToken(token);
            response.setId(user.getId());
            response.setUsername(user.getUsername());
            response.setRole(user.getRole());
            response.setAvatar(user.getAvatar());
            return response;
        } catch (Exception e) {
            throw new BusinessException("用户名或密码错误");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void register(RegisterRequest registerRequest) {
        // 检查用户名是否已存在
        if (userMapper.findByUsername(registerRequest.getUsername()) != null) {
            throw new BusinessException("用户名已存在");
        }

        User user = new User();
        user.setUsername(registerRequest.getUsername());
        user.setPassword(passwordEncoder.encode(registerRequest.getPassword()));
        user.setRole("USER");
        user.setStatus(1);
        userMapper.insert(user);
    }

    @Override
    public void logout() {
        SecurityUtils.clearLoginUser();
        SecurityContextHolder.clearContext();
    }

    @Override
    public AuthResponse getCurrentUserInfo() {
        User user = getCurrentUser();
        AuthResponse response = new AuthResponse();
        response.setId(user.getId());
        response.setUsername(user.getUsername());
        response.setRole(user.getRole());
        response.setAvatar(user.getAvatar());
        return response;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void changePassword(String oldPassword, String newPassword) {
        User user = getCurrentUser();

        // 验证旧密码
        if (!passwordEncoder.matches(oldPassword, user.getPassword())) {
            throw new BusinessException("旧密码错误");
        }

        // 更新密码
        User updateUser = new User();
        updateUser.setId(user.getId());
        updateUser.setPassword(passwordEncoder.encode(newPassword));
        userMapper.update(updateUser);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String updateAvatar(MultipartFile file) {
        User user = getCurrentUser();

        // 删除旧头像
        if (user.getAvatar() != null && !user.getAvatar().isEmpty()) {
            fileUtil.deleteFile(user.getAvatar());
        }

        // 上传新头像
        String avatarUrl = fileUtil.uploadFile(file, "avatars");

        // 更新用户头像
        User updateUser = new User();
        updateUser.setId(user.getId());
        updateUser.setAvatar(avatarUrl);
        userMapper.update(updateUser);

        return avatarUrl;
    }

    @Override
    public User getCurrentUser() {
        return findById(getCurrentUserId());
    }

    @Override
    public Long count() {
        return userMapper.count(new HashMap<>());
    }

    private UserDTO convertToDTO(User user) {
        UserDTO userDTO = new UserDTO();
        BeanUtils.copyProperties(user, userDTO);
        userDTO.setPassword(null); // 不返回密码
        return userDTO;
    }
} 